﻿using MediatR;
using Newtonsoft.Json;
using RBAC_Uthorization.Domain;
using RBAC_Uthorization.Domain.Entity;
using RBAC_Uthorization.Infrstructre.Interface;
using RBAC_Uthorization.Read.API.Application.Command.MenuCommand;
using RBAC_Uthorization.Read.API.DTO;
using RBAC_Uthorization.Read.API.DTO.Response.Menu;
using RBAC_Uthorization.Read.API.Extensions;
using StackExchange.Redis;

namespace RBAC_Uthorization.Read.API.Application.CommandHandlers.MenuHandler
{
    public class MenuTreeShowCommandHandlers : IRequestHandler<MenuTreeShowCommand, ApiResult<List<MenuTreeShowDto>>>
    {
        private readonly IMenuRepository _menuRepository;
        private readonly IFunctionRepository _functionRepository;
        private readonly ILogger<MenuTreeShowCommandHandlers> _logger;
        private readonly IConfiguration _configuration;
        private readonly RedisConnectionService db;

        public MenuTreeShowCommandHandlers(IMenuRepository menuRepository, ILogger<MenuTreeShowCommandHandlers> logger, IFunctionRepository functionRepository, IConfiguration configuration, RedisConnectionService db)
        {
            _menuRepository = menuRepository;
            _logger = logger;
            _functionRepository = functionRepository;
            _configuration = configuration;
            this.db = db;
        }

        public async Task<ApiResult<List<MenuTreeShowDto>>> Handle(MenuTreeShowCommand request, CancellationToken cancellationToken)
        {
            
            try
            {
            

                if (_configuration["Redis:Redisif"] == "1")
                {
                   
                
                    var cacheKey = $"MenuTree_{request.sys_id}";
                    var cachedData = await db.GetAsync(cacheKey);

                    if (!string.IsNullOrEmpty(cachedData))
                    {
                        var cachedMenuTree = JsonConvert.DeserializeObject<List<MenuTreeShowDto>>(cachedData);
                 
                        return new ApiResult<List<MenuTreeShowDto>>
                        {
                            Data = cachedMenuTree,
                            Code = ResultCode.Ok,
                            Message = "菜单树形查询成功（缓存）"
                        };
                    }
                }

                var menus = await _menuRepository.GetAllAsunc(x => x.sys_id == request.sys_id && x.del_flag == 0);
                if (_configuration["Redis:Redisif"] == "1")
                {
                    db.SetAsync($"Menu_{request.sys_id}", JsonConvert.SerializeObject(menus));
                }
                var menuTree = BuildMenuTree(menus, 0);

               
                if (_configuration["Redis:Redisif"] == "1")
                {
                   
                    await db.SetAsync($"MenuTree_{request.sys_id}",
JsonConvert.SerializeObject(menuTree));
                }

                return new ApiResult<List<MenuTreeShowDto>>
                {
                    Data = menuTree,
                    Code = ResultCode.Ok,
                    Message = "菜单树形查询成功"
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理MenuTreeShowCommand时发生错误");
                return new ApiResult<List<MenuTreeShowDto>>
                {
                    Code = ResultCode.Fail,
                    Message = "处理菜单树形时发生错误"
                };
            }
        }

        private List<MenuTreeShowDto> BuildMenuTree(List<sys_menu> menus, int parentId)
        {
            var menu = menus.Where(m => m.parent_id == parentId)
                .Select(m => new MenuTreeShowDto
                {
                    value = m.id.ToString(),
                    label = m.menu_name,
                    isButton = m.type == 2,
                    children = m.type == 2 ? GetButtonChildren(m.id) : BuildMenuTree(menus, m.id).Count() > 0 ? BuildMenuTree(menus, m.id) : null
                })
                .ToList();

            return menu;
        }

        private List<MenuTreeShowDto> GetButtonChildren(int menuId)
        {
            var functions = _functionRepository.GetAllAsunc(f => f.menu_id == menuId).Result;
            return functions.Select(f => new MenuTreeShowDto
            {
                value = $"{f.id}-{menuId}",
                label = f.permission_name,
                isButton = true,
                children = null
            }).ToList();
        }
    }
}
